/*=========================================================================

Program:   Virtual Surgery
Language:  C++
Date:      2009-9-1
Version:   0.1
Mail:		   nelfylee@gmail.com

Copyright (c) 2009 Nelfy Lee. All rights reserved.

=========================================================================*/

#include "MainWindow.h"
#include "LoadDicomSeriesThread.h"
#include "DisplayFramework.h"
#include "ControlPanelDock.h"
#include "SourcePipelineDock.h"
#include "PipelineTreeView.h"
#include "DisplayModel.h"
#include "ToolBar.h"
#include "SourceIO.h"

#include "itkTextOutput.h"

#include <QtTest/QTest>
#include <QMenuBar>
#include <QStatusBar>
#include <QSignalMapper>
#include <QTimer>
#include <QFileDialog>


const char *version = "Virtual Surgery 0.01  ";
ToolBar* g_toolBar = NULL;


MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags flags)
: QMainWindow(parent, flags)
{
	setObjectName("MainWindow");
	setWindowTitle(QString(version));

	m_pipeline = new PipelineModel;	// Init pipeline model first
	m_pipelineDock = new SourcePipelineDock(this);
	m_controlPanelDock = new ControlPanelDock(this);
	m_displayFramework = new DisplayFramework(this);
	m_displayModel = new DisplayModel();
	m_sourceIO = new SourceIO(m_pipeline);
	m_pipelineTreeView = new PipelineTreeView(m_pipelineDock);

	
	setupMenuBar();
	setupToolBar();
	setupDockWidgets();
	setupPanels();
	setDockOptions();
	setupStatusbar();

	itk::OutputWindow::SetInstance(itk::TextOutput::New().GetPointer());
}


MainWindow::~MainWindow()
{
	return;
}

// 
// void MainWindow::slotSourceSelected(const QString& )
// {
// 	QStandardItem *item = m_pipeline->itemFromIndex(index);
// 
// 	slotChangeTitleInfo(item->text());
// }


void MainWindow::postShow()
{
	m_displayFramework->initViews();
	m_displayFramework->resetLayout();
	m_pipelineTreeView->postShow();

	//openTesting();
}

void
MainWindow::slotProgressStart(QString string)
{	
	m_labelStatusMsg->setText(string);
	statusBar()->addWidget(m_progressBar);
	m_progressBar->show();
	m_progressBar->setStart();
}

void 
MainWindow::slotProgressUpdate(int value)
{
	m_progressBar->setValue(value);
}


void 
MainWindow::slotProgressDone()
{
	m_labelStatusMsg->setText("Ready");
	m_progressBar->setDone();
	m_progressBar->hide();
	statusBar()->removeWidget(m_progressBar);
}


void 
MainWindow::setupToolBar()
{
	g_toolBar = new ToolBar(QString("ToolBar"), this);
	addToolBar(g_toolBar);


	connect(g_toolBar, SIGNAL(emitOpenFile()), SLOT(openFile()));
	connect(g_toolBar, SIGNAL(emitOpenDir()), SLOT(openDicomDir()));
	connect(g_toolBar, SIGNAL(emitSaveSource()), SLOT(saveSource()));
	connect(g_toolBar, SIGNAL(emitRemoveSource()), SLOT(removeSource()));
	connect(g_toolBar, SIGNAL(emitLinkCameras(bool)), m_displayFramework, SLOT(slotLink3DViewCameras(bool)));
	connect(g_toolBar, SIGNAL(emitPickSeed()), m_displayModel, SLOT(slotPickSeed()));
	connect(g_toolBar, SIGNAL(emitRemoveSeed(QString)), m_displayModel, SLOT(slotRemoveSeed(QString)));
	connect(g_toolBar, SIGNAL(emitSeedSelected(QString)), m_displayModel, SLOT(slotSeedSelected(QString)));
	connect(g_toolBar, SIGNAL(emitCreateSurfaceSource()), m_pipelineTreeView, SLOT(slotCreateSurfaceSource()));
	connect(m_displayModel, SIGNAL(emitUpdateSeeds(const QStringList&)), 
		g_toolBar, SLOT(slotUpdateSeeds(const QStringList&)));

	//connect(m_toolbar, SIGNAL(emitSeedSelected(QString)), m_displayModel, SLOT(slotSeedSelected(QString)));
}

void 
MainWindow::setupMenuBar()
{
	// File Menu
	QMenu *menu = menuBar()->addMenu(tr("&File"));

	QAction *action = menu->addAction(tr("Open File"));
	connect(action, SIGNAL(triggered()), this, SLOT(openFile()));
	action = menu->addAction(tr("Open Dir"));
	connect(action, SIGNAL(triggered()), SLOT(openDicomDir()));
	action = menu->addAction(tr("Open Testing"));
	connect(action, SIGNAL(triggered()), SLOT(openTesting()));

	menu->addSeparator();

	action = menu->addAction(tr("Save"));
	connect(action, SIGNAL(triggered()), SLOT(saveSource()));
	action = menu->addAction(tr("Delete"));
	connect(action, SIGNAL(triggered()), SLOT(removeSource()));

	menu->addSeparator();

	menu->addAction(tr("&Quit"), this, SLOT(close()));


	// View Menu
	m_viewMenu = menuBar()->addMenu(tr("&View"));

	// Operation

	menu = menuBar()->addMenu(tr("&Operation"));
	action = menu->addAction(tr("Smoothing"));
	//connect
	action = menu->addAction(tr("Thresholding"));
	menu->addSeparator();

	action = menu->addAction(tr("Liver Segmentation"));
	action = menu->addAction(tr("Vessel Segmentation"));

}



void 
MainWindow::setDockOptions()
{
	DockOptions opts;
	opts |= AnimatedDocks;
	//opts |= AllowNestedDocks;
	opts |= AllowTabbedDocks;
	//opts |= ForceTabbedDocks;
	//opts |= VerticalTabs;

	QMainWindow::setDockOptions(opts);
}


QAction *
addAction(QMenu *menu, const QString &text, QActionGroup *group, QSignalMapper *mapper,
					int id)
{
	bool first = group->actions().isEmpty();
	QAction *result = menu->addAction(text);
	result->setCheckable(true);
	result->setChecked(first);
	group->addAction(result);
	QObject::connect(result, SIGNAL(triggered()), mapper, SLOT(map()));
	mapper->setMapping(result, id);
	return result;
}


void 
MainWindow::setupDockWidgets()
{

	//m_pipelineDock->setMaximumWidth(200);
	//m_controlPanelDock->setMaximumWidth(200);

	// setup menu items
	m_viewMenu->addAction(m_pipelineDock->toggleViewAction());
	m_viewMenu->addAction(m_controlPanelDock->toggleViewAction());

	
	m_pipelineDock->SetPipelineView((QAbstractItemView*)m_pipelineTreeView);
	m_pipelineTreeView->setModel(m_pipeline);
	m_pipelineTreeView->setDisplayModel(m_displayModel);

	connect(m_pipeline, SIGNAL(emitSourceAdded(const QModelIndex&)), 
		m_pipelineTreeView, SLOT(slotSourceAdded(const QModelIndex&)));

	connect(m_pipeline, SIGNAL(emitSetBase(const QModelIndex&)),
		m_displayFramework, SLOT(slotSetBase(const QModelIndex&)));


	m_pipelineDock->SetPipelineView(m_pipelineTreeView);

	m_displayFramework->setPipeline(m_pipeline);
	m_controlPanelDock->setPipeline(m_pipeline);
	m_controlPanelDock->setDisplayModel(m_displayModel);
	m_displayModel->setPipelineModel(m_pipeline);
	m_pipeline->setDisplayModel(m_displayModel);
	m_displayModel->setDisplayFramework(m_displayFramework);
	


	connect(m_controlPanelDock, SIGNAL(emitProgressStart(QString)), SLOT(slotProgressStart(QString)));
	connect(m_controlPanelDock, SIGNAL(emitProgressUpdate(int)), SLOT(slotProgressUpdate(int)));
	connect(m_controlPanelDock, SIGNAL(emitProgressDone()), SLOT(slotProgressDone()));


	addDockWidget(Qt::LeftDockWidgetArea, m_pipelineDock);
	addDockWidget(Qt::LeftDockWidgetArea, m_controlPanelDock);

	setCentralWidget(m_displayFramework);

	connect(m_pipelineTreeView, SIGNAL(emitSourceSelected(const QString&)), SLOT(slotChangeTitleInfo(const QString&)));

	connect(m_sourceIO, SIGNAL(emitProgressStart(QString)), SLOT(slotProgressStart(QString)));
	connect(m_sourceIO, SIGNAL(emitProgressUpdate(int)),this, SLOT(slotProgressUpdate(int)));
	connect(m_sourceIO, SIGNAL(emitProgressDone()), SLOT(slotProgressDone()));
}



void MainWindow::setupPanels()
{

}

void 
MainWindow::setupStatusbar()
{
	statusBar()->setMinimumHeight(25);

	m_labelStatusMsg = new QLabel("Ready", this);
	m_labelStatusMsg->setMinimumWidth(300);

	statusBar()->addWidget(m_labelStatusMsg, 2000);

	m_progressBar = new ProgressBar(statusBar());
	m_progressBar->hide();
}


void 
MainWindow::openTesting()
{
	static int times = 1;

	if ( times == 1)
	{
		//QString dir("E:/Research/data/TestData/ChangeGGO_JeongJeongSun/Series2_Float");

// 		QString dir("E:/Research/data/GGO segmentation/PNGGO/18322484");
// 		QStringList list = dir.split("/");
// 		m_sourceIO->loadDicomSeries(dir,  list.at(list.size()-1));

	
		QString filename("E:/Research/build/6.bmp");

		QStringList list = filename.split("/");
		m_sourceIO->loadFile(filename, list.at(list.size()-1));
	}
	else if ( times == 2)
	{
		QString dir("E:/Research/data/TestData/NoChange_KimDalSu/Series6_Float");

		QStringList list = dir.split("/");
		m_sourceIO->loadDicomSeries(dir,  list.at(list.size()-1));
	}
	else if ( times == 3)
	{
		QString dir("E:/Research/data/TestData/SlightlyChange_17382661/2nd");

		QStringList list = dir.split("/");
		m_sourceIO->loadDicomSeries(dir,  list.at(list.size()-1));
	}
	else
		return;

	times++;
}


void 
MainWindow::openDicomDir()
{	
	QString dir = QFileDialog::getExistingDirectory(this,
		tr("Open Directory"), "", QFileDialog::ShowDirsOnly);

	qDebug("Open dir[%s]", dir.toLatin1().data());

	if ( dir.isEmpty())
		return;

	QStringList list = dir.split("/");
	m_sourceIO->loadDicomSeries(dir,  list.at(list.size()-1));
}


void 
MainWindow::openFile()
{
	QString filename = QFileDialog::getOpenFileName(this,
		tr("Open File"), "", tr("Image Files (*.vtk *.dcm *.bmp *mhd)"));

	qDebug("Open file[%s]", filename.toLatin1().data());

	if ( filename.isEmpty())
		return;

	QStringList list = filename.split("/");
	m_sourceIO->loadFile(filename, list.at(list.size()-1));
}


void
MainWindow::saveSource()
{
	m_pipelineTreeView->slotSaveSource();
}


void
MainWindow::removeSource()
{
	m_pipelineTreeView->slotRemoveSource();
}

void MainWindow::slotChangeTitleInfo(const QString& str)
{
	if ( str.isEmpty())
		m_titleInfo = "";
	else
		m_titleInfo = QString("  [%1]").arg(str);

	setWindowTitle(QString(version) + m_titleInfo);
}
